#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <dirent.h>
#include <unistd.h>
#include <vector>
#include <sstream>
#include <fstream>
#include <sys/io.h>
#include <sys/times.h>
#include <iomanip> // setw()
using namespace std;

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
#include "opencv2/ximgproc.hpp"
using namespace cv::ximgproc;


// ----------------------------------------------------- //
static bool readVideo(string strVideoPath);
static void onMouse( int event, int x, int y, int, void* );
void for_showing();

// global variables ------------------------------------ //
cv::Mat CurRGB, CurMono;
int     g_curKeyBoardPushed;
int     g_FrmNum = 0, g_curFrm = 0;

// ----------------------------------------------------- //
int main(int argc, char** argv)
{
	cout << ">> ----" << "\n" << endl;
	
	cv::namedWindow("win1");
	setMouseCallback("win1", onMouse, 0);
	readVideo(argv[1]);

	cout << "\n" << ">> ----" << endl;
	return 0;
}

static bool readVideo(string strVideoPath)
{
	// openning video
	cv::VideoCapture capture;
	capture = cv::VideoCapture(strVideoPath.c_str());
	double dFrameNum = -1, dFPS = -1, dImgWid = -1, dImgHei = -1;
	if (capture.isOpened())
	{
		dFrameNum = capture.get(CV_CAP_PROP_FRAME_COUNT);
		dFPS      = capture.get(CV_CAP_PROP_FPS);
		dImgWid   = capture.get(CV_CAP_PROP_FRAME_WIDTH);
		dImgHei   = capture.get(CV_CAP_PROP_FRAME_HEIGHT);
		g_FrmNum  = (int)dFrameNum;
		
		int sta = 1217;
		int end = dFrameNum;
		for (int i = sta; i < end; i++) {
			if (g_curFrm < sta) {
				g_curFrm = sta;
			}
			if (g_curFrm >= end) {
				g_curFrm = end - 1;
			}
			capture.set(CV_CAP_PROP_POS_FRAMES, double(g_curFrm));
			capture.read(CurRGB);
			for_showing();
			g_curKeyBoardPushed = waitKey();
			switch (g_curKeyBoardPushed) 
			{
			case 113: { // q
				g_curFrm -= 1;
				if (g_curFrm < sta) {
					g_curFrm = sta;
				}
				break;}
			case 101: { // e
				g_curFrm += 1;
				if (g_curFrm >= end) {
					g_curFrm = end - 1;
				}
				break;}
			case 115: { // s
				std::size_t found0 = strVideoPath.rfind(".");
				std::size_t found1 = strVideoPath.rfind("/");
				if (found0 != std::string::npos && found1 != std::string::npos) {
					stringstream ss;
					ss << g_curFrm;
					string str = "./data" + 
					             strVideoPath.substr(found1, found0 - found1) + 
					             "_" + ss.str() + ".jpg";
					if (access(str.c_str(), 0) == -1) {
						imwrite(str.c_str(), CurRGB);
						cout << ">> save success, info:" << str.c_str() << endl;
					}
					else
						cout << ">> file exists" << endl;
				}
				break;
			}
			case 27: { 	// esc
				g_curFrm = -1;
				break;
				}
			default:	// do nothing
				break;
			}
			if (g_curFrm < 0) {
				break;
			}
		}
		capture.release();
		CurRGB.release();
		CurMono.release();
		destroyWindow("win1");
		cout << ">> release all memory" << endl;
	}
	else { 
		cout << ">> error. fail to open video. file: " << strVideoPath.c_str() << endl; 
		return false; 
	}
	
	return true;
}

// paint region
void for_showing() 
{
	stringstream ss;
	ss << g_curFrm;
	ss << " / "; 
	ss << g_FrmNum;
	string str = ss.str();
	cv::putText(CurRGB, str.c_str(), cv::Point(5, 23), 
				FONT_HERSHEY_SIMPLEX, 0.8, 
				Scalar(0, 255, 255, 255), 2, 8);
	imshow("win1", CurRGB);
}



static void onMouse( int event, int x, int y, int, void* )
{

}









